fix: improve notification bubble panel hide animation#1490
fix: improve notification bubble panel hide animation#149018202781743 merged 1 commit intolinuxdeepin:masterfrom
Conversation
Reviewer's GuideImproves the notification bubble panel’s disappearance behavior by delaying panel hide until after a 400ms bubble removal animation, and adjusts ListView sizing to better accommodate animated content. Sequence diagram for delayed hide of notification bubble panelsequenceDiagram
participant NotificationSource
participant BubbleModel
participant BubblePanel
participant QML_BubbleView
participant QTimer
NotificationSource->>BubbleModel: removeNotification(id)
BubbleModel-->>BubblePanel: bubbleCountChanged()
BubblePanel->>BubblePanel: onBubbleCountChanged()
BubblePanel->>BubblePanel: isEmpty = m_bubbles.items().isEmpty()
BubblePanel->>BubblePanel: visible = !isEmpty && enabled()
alt visible is true
BubblePanel->>BubblePanel: setVisible(true)
BubblePanel-->>QML_BubbleView: remain visible
else visible is false
BubblePanel->>QTimer: singleShot(400ms, this, lambda)
QML_BubbleView->>QML_BubbleView: ListView remove Transition
QML_BubbleView->>QML_BubbleView: SequentialAnimation
QML_BubbleView->>QML_BubbleView: ListView.delayRemove = true
QML_BubbleView->>QML_BubbleView: NumberAnimation x -> 360 (400ms)
QML_BubbleView->>QML_BubbleView: ListView.delayRemove = false
QTimer-->>BubblePanel: timeout after 400ms
BubblePanel->>BubblePanel: setVisible(false)
end
Updated class diagram for BubblePanel notification visibility logicclassDiagram
class BubblePanel {
- m_bubbles
+ onNotificationStateChanged(id, processedType) void
+ onBubbleCountChanged() void
+ addBubble(id) void
+ setVisible(visible) void
+ enabled() bool
}
class QTimer {
+ singleShot(msec, receiver, slot) void
}
BubblePanel ..> QTimer : uses_singleShot_for_delayed_hide
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The QTimer::singleShot in onBubbleCountChanged() will hide the panel unconditionally after 400ms even if new bubbles arrived in the meantime; consider checking the current bubble count/enabled state in the lambda or cancelling/reusing a single timer to avoid hiding an active panel.
- In the ListView remove transition, the hardcoded value
to: 360for the x animation couples the animation to a magic number; usingto: widthor a shared constant would make the slide-out behavior robust to future width/layout changes.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The QTimer::singleShot in onBubbleCountChanged() will hide the panel unconditionally after 400ms even if new bubbles arrived in the meantime; consider checking the current bubble count/enabled state in the lambda or cancelling/reusing a single timer to avoid hiding an active panel.
- In the ListView remove transition, the hardcoded value `to: 360` for the x animation couples the animation to a magic number; using `to: width` or a shared constant would make the slide-out behavior robust to future width/layout changes.
## Individual Comments
### Comment 1
<location path="panels/notification/bubble/bubblepanel.cpp" line_range="114-120" />
<code_context>
{
bool isEmpty = m_bubbles->items().isEmpty();
- setVisible(!isEmpty && enabled());
+ const bool visible = !isEmpty && enabled();
+ if (!visible) {
+ QTimer::singleShot(400, this, [this]() {
+ setVisible(false);
+ });
+ } else {
+ setVisible(visible);
+ }
}
</code_context>
<issue_to_address>
**issue (bug_risk):** Delayed hide timer can incorrectly hide the panel after it becomes visible again.
Because `QTimer::singleShot` is unconditional, a call with `visible == false` will still invoke `setVisible(false)` after 400 ms even if a later call with `visible == true` has already made the panel visible. This creates a race where a stale hide timer overrides a newer show.
To fix this, either cancel/gate the hide in the lambda (e.g. re-check `!m_bubbles->items().isEmpty()` and `enabled()` before calling `setVisible(false)`), or track a hide request ID/sequence and only apply the latest one.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| const bool visible = !isEmpty && enabled(); | ||
| if (!visible) { | ||
| QTimer::singleShot(400, this, [this]() { | ||
| setVisible(false); | ||
| }); | ||
| } else { | ||
| setVisible(visible); |
There was a problem hiding this comment.
issue (bug_risk): Delayed hide timer can incorrectly hide the panel after it becomes visible again.
Because QTimer::singleShot is unconditional, a call with visible == false will still invoke setVisible(false) after 400 ms even if a later call with visible == true has already made the panel visible. This creates a race where a stale hide timer overrides a newer show.
To fix this, either cancel/gate the hide in the lambda (e.g. re-check !m_bubbles->items().isEmpty() and enabled() before calling setVisible(false)), or track a hide request ID/sequence and only apply the latest one.
| { | ||
| bool isEmpty = m_bubbles->items().isEmpty(); | ||
| setVisible(!isEmpty && enabled()); | ||
| const bool visible = !isEmpty && enabled(); |
There was a problem hiding this comment.
这个代码要优化下吧,例如它放在qml端,
另外,这个在暂存区域显示的时候,enabled()为false,实际上它不需要延迟隐藏,
e651239 to
c22b928
Compare
| bool isEmpty = m_bubbles->items().isEmpty(); | ||
| setVisible(!isEmpty && enabled()); | ||
| const bool visible = !isEmpty && enabled(); | ||
| if (!visible) { |
There was a problem hiding this comment.
这里换成isEmpty吧,enabled变化应该不需要延迟隐藏,
| #include <QQueue> | ||
|
|
||
| #include <appletbridge.h> | ||
| #include <qtimer.h> |
728400c to
7a5aded
Compare
Changed the bubble panel visibility logic to include a 400ms delay before hiding when there are no notifications. This prevents the panel from disappearing abruptly when the last bubble is removed. The QML ListView now includes a remove transition with smooth exit animation for bubbles. Added QTimer include for delayed hide functionality. Modified the ListView height calculation to use maximum of contentHeight and childrenRect.height to ensure proper layout during animations. Implemented a sequential animation for bubble removal with x-axis slide- out effect. Log: Improved notification bubble animations with smoother hide effects Influence: 1. Test notification bubble appearance and disappearance 2. Verify panel remains visible during bubble removal animations 3. Check that multiple bubbles animate correctly 4. Test edge cases with rapid notification additions/removals 5. Verify panel properly hides after all bubbles are removed 6. Test animation timing and smoothness PMS: BUG-284659
deepin pr auto review这段代码的修改主要是为了优化通知气泡移除时的视觉效果,增加了一个平滑的退出动画。以下是对这段diff的详细审查和改进建议: 1. 代码逻辑与功能分析BubblePanel.cpp 部分:
main.qml 部分:
2. 代码质量与性能问题问题1:时序不匹配cpp中延迟400ms隐藏面板,而qml中动画也是400ms。虽然看似匹配,但存在潜在问题:
问题2:内存与性能
问题3:状态管理
3. 安全性问题
4. 改进建议建议1:优化时序控制void BubblePanel::onBubbleCountChanged()
{
bool isEmpty = m_bubbles->items().isEmpty();
if (isEmpty) {
// 确保动画完成后再隐藏,可以适当增加余量
QTimer::singleShot(450, this, [this]() {
if (m_bubbles->items().isEmpty()) { // 再次检查状态
setVisible(false);
}
});
} else {
setVisible(true && enabled());
}
}建议2:增加状态跟踪在BubblePanel类中添加成员变量跟踪动画状态: // 在头文件中添加
private:
bool m_isAnimating = false;
QTimer* m_hideTimer = nullptr;
// 在构造函数中初始化
m_hideTimer = new QTimer(this);
m_hideTimer->setSingleShot(true);
connect(m_hideTimer, &QTimer::timeout, this, [this]() {
if (!m_isAnimating && m_bubbles->items().isEmpty()) {
setVisible(false);
}
});
// 修改onBubbleCountChanged
void BubblePanel::onBubbleCountChanged()
{
bool isEmpty = m_bubbles->items().isEmpty();
if (isEmpty && !m_isAnimating) {
m_hideTimer->start(450);
} else {
m_hideTimer->stop();
setVisible(true && enabled());
}
}建议3:QML动画优化ListView.onRemove: SequentialAnimation {
PropertyAction {
target: delegateItem
property: "ListView.delayRemove"
value: true
}
NumberAnimation {
target: delegateItem
property: "x"
to: 360
duration: 400
easing.type: Easing.InExpo
onRunningChanged: {
if (!running) {
// 通知cpp动画完成
BubblePanel.animationFinished()
}
}
}
PropertyAction {
target: delegateItem
property: "ListView.delayRemove"
value: false
}
}建议4:增加边界检查在cpp中增加对BubblePanel对象生命周期的检查: QTimer::singleShot(400, this, &BubblePanel::safeHide);
void BubblePanel::safeHide()
{
if (isVisible() && m_bubbles->items().isEmpty()) {
setVisible(false);
}
}5. 总结这段代码的主要改进方向应该是:
建议采用状态机模式来管理气泡面板的显示/隐藏和动画状态,这样可以更清晰地处理各种状态转换。 |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: 18202781743, qxp930712 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Changed the bubble panel visibility logic to include a 400ms delay before hiding when there are no notifications. This prevents the panel from disappearing abruptly when the last bubble is removed. The QML ListView now includes a remove transition with smooth exit animation for bubbles.
Added QTimer include for delayed hide functionality. Modified the ListView height calculation to use maximum of contentHeight and childrenRect.height to ensure proper layout during animations. Implemented a sequential animation for bubble removal with x-axis slide- out effect.
Log: Improved notification bubble animations with smoother hide effects
Influence:
PMS: BUG-284659
Summary by Sourcery
Improve notification bubble panel visibility and removal animations to provide a smoother hide experience when bubbles are cleared.
New Features:
Bug Fixes:
Enhancements: